#include "parser.tab.hpp"
#include "ast.h"
#include "ir.h"
#include "reg_alloc.h"
#include "code.h"
#include "ir_optimizer.h"
#include "dead_code_elimination.h"
#include "code_peephole.h"
#include <filesystem>
#include <cstdio>
#include <fstream>
#include <string>
#include <iostream>
using namespace ast;
using namespace ir;
using namespace reg_alloc;
using namespace dead_code_elimination;
using namespace std;
using namespace filesystem;

extern FILE* yyin;
extern int yyparse(unique_ptr<BaseAST>& root);

int main()
{
    yyin = stdin;
    unique_ptr<BaseAST> root;
    yyparse(root);
    fclose(yyin);
    CompUnitAST* comp_unit = dynamic_cast<ast::CompUnitAST*>(root.get());
    IR ir = IRGenerator().Generate(*comp_unit);
    ir::Optimizer::Optimize(ir);
    IR dead_code_eliminated_ir = DeadCodeEliminator().Optimize(ir);
    IR reg_alloc_ir;
    for (ir::Function& func : dead_code_eliminated_ir.funcs)
    {
        ir::Function new_func = move(RegAllocator().Allocate(func));
        reg_alloc_ir.funcs.push_back(move(new_func));
    }
    code::Code code = code::CodeGenerator().Generate(reg_alloc_ir);
    code::peephole_optimizer::peephole_optimize(code);
    cout << code.ToString();
    return 0;
}